#ifndef _LOG_H_
#define _LOG_H_ 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
#include <sys/stat.h>
#include "opt.h"

#define LOG_CONF_LEVEL_ALL "ALL"
#define LOG_CONF_LEVEL_TRACE "TRACE"
#define LOG_CONF_LEVEL_DEBUG "DEBUG"
#define LOG_CONF_LEVEL_INFO "INFO"
#define LOG_CONF_LEVEL_NOTICE "NOTICE"
#define LOG_CONF_LEVEL_WARNING "WARNING"
#define LOG_CONF_LEVEL_ERROR "ERROR"
#define LOG_CONF_LEVEL_CRITICAL "CRITICAL"

enum {
    LOG_OUTPUT = 0,
    LOG_FATAL = 0x1,
    LOG_ERROR = 0x2,
    LOG_WARN = 0x4,
    LOG_NOTICE = 0x8,
    LOG_INFO = 0x10,
    LOG_DEBUG = 0x20,
    LOG_TRACE = 0x40,
};

typedef struct log_s {
    FILE* fp;
    char file_name[64];
    int log_size;
    int level;
    int buf_size;
    char *buffer;
} log_t;
extern log_t Log;

#define log_trace(fmt, arg...) log_write(&Log, LOG_TRACE, "[TRACE]{ %s, %d } " fmt "\n", __FUNCTION__, __LINE__, ##arg)
#define log_debug(fmt, arg...) log_write(&Log, LOG_DEBUG, "[DEBUG]{ %s, %d } " fmt "\n", __FUNCTION__, __LINE__, ##arg)
#define log_info(fmt, arg...) log_write(&Log, LOG_INFO, "[INFO] - " fmt "\n", ##arg)
#define log_notice(fmt, arg...) log_write(&Log, LOG_NOTICE, "[NOTICE] - " fmt "\n", ##arg)
#define log_warn(fmt, arg...) log_write(&Log, LOG_WARN, "[WARNING] - " fmt "\n", ##arg)
#define log_error(fmt, arg...) log_write(&Log, LOG_ERROR, "[ERROR] - " fmt "\n", ##arg)
#define log_syserr(fmt, arg...) log_write(&Log, LOG_ERROR, "[SYSERR]{ %s, %d } " fmt "(errno:%d, %s)\n", __FUNCTION__, __LINE__, ##arg, errno, strerror(errno))
#define log_fatal(fmt, arg...) log_write(&Log, LOG_FATAL, fmt "\n", ##arg)
#define log_output(fmt, arg...) log_write(&Log, LOG_OUTPUT, fmt "\n", ##arg)

#define log_buf(e_level, buf, len) log_buffer(&Log, e_level, (unsigned char*)buf, len)
#define log_level(str_level)    log_set_level(&Log, str_level)
#define log_put_mdc(a, b) \
    do {                  \
    } while (0)

extern int log_initv(int argc, char** argv);
extern int log_init(char* output, int log_size, char* level);
extern int log_write(log_t* log, int level, char* fmt, ...);
extern int log_buffer(log_t* log, int level, unsigned char* buf, int buf_len);
extern int log_set_level(log_t *log, char *level);
#endif